/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-12-22     RT-Thread    first version
 */

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

//user define
#include "GlobalVar.h"
#include "IO_Driver.h"
#include "MotorDriver.h"
#include "ActionQueue.h"

//Machine error quantity
static uint32_t error_num;

static void AppInit();
static void BusDeviceInit();
static void Module_Init();
static void Self_Test();
static void STM32_BSP_Init();


int main(void)
{
      DelayMs(100);              /* 上电延时 **/
      STM32_BSP_Init();          /* 片上外设初始化 **/
      BusDeviceInit();           /* 总线设备创建与注册 */
      GlobalVarInit();           /* 全局变量初始化 **/
      Module_Init();             /* 模块初始化 **/
      Self_Test();               /* 设备自检 **/
      AppInit();
      return RT_EOK;
}


/*****user define **/
void STM32_BSP_Init()
{
    void IO_Init();
}

void BusDeviceInit()
{

    //SPI  I2C  UART CAN


}

void Self_Test()
{
    if(machine_info.address != 0x01)
        return;
    rt_thread_mdelay(1000);

    for (uint8_t board_num = 2; board_num < 5; ++board_num)
    {
        //查询2号板
        Err_LED_ON(NULL);
        rt_thread_mdelay(500);
        //等待2号板成功启动
        Err_LED_OFF(NULL);
        rt_thread_mdelay(500);
    }

    if(error_num != 0)
    {
        LOG_E("self test failed and please reboot,error number is %d.",
                error_num);
        error_num = 0;
        while(1);
    }
}


void Module_Init()
{
    //重置所有电机芯片参数
}

void MotorDriverInit()
{
    rt_err_t ret;
    /** create and startup 5 motor driver about.**/
    for (int driver_num = 1; driver_num <= 5; ++driver_num)
    {
        /** create and startup motor driver msg queue.**/
        task.motor_driver[driver_num].task_msg_queue = rt_mq_create("motor",
                8,
                1,
                RT_IPC_FLAG_FIFO);
        if(task.motor_driver[driver_num].task_msg_queue == RT_NULL)
        {
            LOG_E("motor dirver msg queue create failed.");
            error_num++;
        }

        /** create and startup motor driver thread.**/
        task.motor_driver[driver_num].thread = rt_thread_create("motor",
                Motor_Driver_Task_Ptr[driver_num],
                NULL,
                512,
                20,
                5);
        if(task.motor_driver[driver_num].thread == RT_NULL)
        {
            LOG_E("motor dirver create failed.");
            error_num++;
        }
        else
        {
            ret = rt_thread_startup(task.motor_driver[driver_num].thread);
            if(ret != RT_EOK)
            {
                LOG_E("motor dirver start up failed.");
                error_num++;
            }
        }

        /** create and startup motor driver complete semphore.**/
        task.motor_driver[driver_num].complete = rt_sem_create("mot", 0, RT_IPC_FLAG_FIFO);
        if(task.motor_driver[driver_num].complete == RT_NULL)
        {
            LOG_E("motor dirver complete semphore create failed.");
            error_num++;
        }
    }
}


void IODriverInit()
{
    rt_err_t ret;
    /** create and startup io driver thread.**/
    task.IO_driver.thread = rt_thread_create("io", IO_driver_Task, NULL, 512, 20, 5);
    if(task.IO_driver.thread == RT_NULL)
    {
        LOG_E("io dirver create failed.");
        error_num++;
    }
    else
    {
        ret = rt_thread_startup(task.IO_driver.thread);
        if(ret != RT_EOK)
        {
            LOG_E("io dirver start up failed.");
            error_num++;
        }
    }
}

void ActionQueueInit()
{
    if(machine_info.address != 0x01)
        return;

    rt_err_t ret;
    /** create and startup 20 action queue about.**/
    for (int i = 1; i <= 20; ++i)
    {
        /** create and startup 20 action queue semphore.**/
        task.action_queue[i].start_up = rt_sem_create("su", 0, RT_IPC_FLAG_FIFO);
        if(task.action_queue[i].start_up == RT_NULL)
        {
            LOG_E("action queue start up semphore create failed.");
            error_num++;
        }

        task.action_queue[i].complete = rt_sem_create("su", 0, RT_IPC_FLAG_FIFO);
        if(task.action_queue[i].complete == RT_NULL)
        {
            LOG_E("action queue complete semphore create failed.");
            error_num++;
        }

        task.action_queue[i].error = rt_sem_create("su", 0, RT_IPC_FLAG_FIFO);
        if(task.action_queue[i].error == RT_NULL)
        {
            LOG_E("action queue error semphore create failed.");
            error_num++;
        }

        /** create and startup 20 action queue task msg queue.**/
        task.action_queue[i].task_msg_queue = rt_mq_create("0", 8, 50, RT_IPC_FLAG_FIFO);
        if(task.action_queue[i].task_msg_queue == RT_NULL)
        {
            LOG_E("action queue task msg queue create failed.");
            error_num++;
        }

        /** create and startup 20 action queue thread.**/
        task.action_queue[i].thread = rt_thread_create("action_queue", Action_Queue_Task_Ptr[i], NULL, 512, 20, 5);
        if(task.action_queue[i].thread == RT_NULL)
        {
            LOG_E("action queue create failed.");
            error_num++;
        }
        else
        {
            ret = rt_thread_startup(task.action_queue[i].thread);
            if(ret != RT_EOK)
            {
                LOG_E("action queue start up failed.");
                error_num++;
            }
        }
    }
}


void LEDInit()
{
    rt_err_t ret;
    if(task.LED == NULL)
    {
        task.LED = rt_thread_create("tsk_led",
                                    LED_Task,
                                    NULL,
                                    512,
                                    20,
                                    5);
        if(task.LED == NULL)
        {
            LOG_E("led thread have been created failed.");
            error_num++;
        }
        else
        {
            ret = rt_thread_startup(task.LED);
            if(ret != RT_EOK)
            {
                LOG_E("led thread start up failed.");
                error_num++;
            }
        }
    }
}

static void AppInit()
{
    LEDInit();
    MotorDriverInit();
    IODriverInit();
    ActionQueueInit();
    //DevMutexInit();

    if(error_num != 0)
    {
        LOG_E("app init failed and please reboot.");
        error_num = 0;
        while(1);
    }
}


